﻿#coding=utf-8

from ctypes import *
from my_debugger_defines import *

kernel32 = windll.kernel32

class debugger():
	def __init__(self):
		#pass
		self.h_process = None
		self.pid = None
		self.debugger_active = False
	
	def load(self,path_to_exe):
		#参数dwCreationFlags中的标志位控制着进程的创建方式。你若希望新创建的进程独占一个新的控制台窗口，而不是与父进程
		#共用同一个控制台，你可以加上标志位CREATE_NEW_CONSOLE creation_flags = DEBUG_PROCESS
		creation_flags  =   DEBUG_RPOCESS

		#实例化之前定义的结构体
		startupinfo     =   STARTUPINFO()
		process_information =   PROCESS_INFORMATION()

		#在以下两个成员变量的共同作用下，新建进程将在一个单独的窗体中被显示，你可以通过改变结构体STARTUPINFO中的各成员
		#变量的值来控制debugee进程的行为。
		startupinfo.dwFlags     =   0x1
		startupinfo.wShowWindow =   0x0

		#设置结构体STARTUPINFO中的成员变量
		#cb的值，用以表示结构体本身的大小
		startupinfo.cb = sizeof(startupinfo)

		if kernel32.CreateProcessA(path_to_exe,
									None,
									None,
									None,
									None,
									creation_flags,
									None,
									None,
									byref(startupinfo),
									byref(process_information)):
				
			print "[*] We have successfully lauched the process!"
			print "[*] PID: %d" % process_information.dwProcessId
            
            #保存一个指向新建进程的有效句柄,以供后续进程访问使用
			self.h_process = self.open_process(process_information.dwProcessId)
		else:    
			print "[*] Error with error code %d." % kernel32.GetLastError()
            
	def open_process(self,pid):
		#PROCESS_ALL_ACCESS对进程内存的全部操作权限
		#pid,若函数执行成功，将返回一个指向目标进程对象的句柄
		h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)
		return h_process
	def attach(self,pid):
		self.h_process = self.open_process(pid)
		#试图附加到目标进程，若附加失败，则输出提示后返回
		if kernel32.DebugActiveProcess(pid):
			self.debugger_active = True
			self.pid = int(pid)
			self.run()
		else:
			print "[*] Unable to attach to the process."
	def run(self):
		# Now we have to poll the debuggee for
        # debugging events
		while self.debugger_active == True:
			self.get_debug_event()   
           
	def get_debug_event(self):
		debug_event = DEBUG_EVENT()
		continue_status= DBG_CONTINUE
		if kernel32.WaitForDebugEvent(byref(debug_event),INFINITE):
            # We aren't going to build any event handlers
            # just yet. Let's just resume the process for now.
			raw_input("Press a key to continue...")
			self.debugger_active = False
			kernel32.ContinueDebugEvent( \
				debug_event.dwProcessId, \
				debug_event.dwThreadId, \
				continue_status )
	def detach(self):
		if kernel32.DebugActiveProcessStop(self.pid):
			print "[*] Finished debugging. Exiting..."
			return True
		else:
			print "There was an error"
			return False 